package cn.fintecher.pangolin.service.report.task;

import cn.fintecher.pangolin.entity.elastic.BehavioralProcess;
import cn.fintecher.pangolin.entity.elastic.CaseFollowupRecord;
import cn.fintecher.pangolin.entity.elastic.CaseTransferLog;
import cn.fintecher.pangolin.entity.mysql.CaseInfo;
import cn.fintecher.pangolin.entity.mysql.QCaseInfo;
import cn.fintecher.pangolin.entity.mysql.User;
import cn.fintecher.pangolin.service.report.elastic.CaseFollowRecordElastic;
import cn.fintecher.pangolin.service.report.elastic.CaseTransferLogElastic;
import cn.fintecher.pangolin.service.report.repository.CaseInfoRepository;
import org.apache.commons.collections4.IterableUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @Auther: xiaqun
 * @Description:
 * @Date: 15:16 2019/12/10
 */

@Service("behavioralProcessTask")
public class BehavioralProcessTask {
    @Autowired
    private CaseTransferLogElastic caseTransferLogElastic;

    @Autowired
    private CaseInfoRepository caseInfoRepository;

    @Autowired
    private CaseFollowRecordElastic caseFollowRecordElastic;

    /**
     * 生成行为过程历史数据
     */
    @Async
    public CompletableFuture<BehavioralProcess> doTask(User user, Date date) {
        DateTime dateTime = new DateTime(date);
        Date endDate = dateTime.plusDays(1).toDate();
        BehavioralProcess process = new BehavioralProcess();
        process.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        process.setDepartId(user.getDepartment().getId()); //部门ID
        process.setDepartName(user.getDepartment().getName()); //部门名称
        process.setDepartCode(user.getDepartment().getDepartCode()); //部门code
        process.setReportDate(date); //报表统计时间
        process.setUserId(user.getId()); //用户ID
        process.setUserName(user.getRealName()); //用户名称

        Iterable<CaseInfo> caseInfoIterable = caseInfoRepository.findAll(QCaseInfo.caseInfo.currentCollector.id.eq(user.getId()));
        List<CaseInfo> caseInfoList = IterableUtils.toList(caseInfoIterable);
        int currentCollecting = caseInfoList.size();
        BoolQueryBuilder builder = new BoolQueryBuilder();
        builder.must(QueryBuilders.matchPhraseQuery("outUserId.keyword", user.getId()));
        builder.must(QueryBuilders.rangeQuery("operatorTime").gte(date.getTime()));
        builder.must(QueryBuilders.rangeQuery("operatorTime").lt(endDate.getTime()));
        Iterable<CaseTransferLog> caseTransferLogIterable = caseTransferLogElastic.search(builder);
        List<CaseTransferLog> caseTransferLogs = IterableUtils.toList(caseTransferLogIterable);
        int outCaseNum = 0;
        if (!caseTransferLogs.isEmpty()) {
            Map<String, List<CaseTransferLog>> listMap = caseTransferLogs.stream().collect(Collectors.groupingBy(CaseTransferLog::getCaseId));
            for (Map.Entry<String, List<CaseTransferLog>> entry : listMap.entrySet()) {
                boolean flag = false;
                for (CaseInfo caseInfo : caseInfoList) {
                    if (entry.getKey().equals(caseInfo.getId())) {
                        flag = true;
                        break;
                    }
                }
                if (!flag) {
                    outCaseNum++;
                }
            }
        }
        process.setCollectingNumber(currentCollecting + outCaseNum); //当日持有案件数

        builder = new BoolQueryBuilder();
        builder.must(QueryBuilders.matchPhraseQuery("operatorId.keyword", user.getId()));
        builder.must(QueryBuilders.rangeQuery("operateTime").gte(date.getTime()));
        builder.must(QueryBuilders.rangeQuery("operateTime").lte(endDate.getTime()));
        Iterable<CaseFollowupRecord> recordIterable = caseFollowRecordElastic.search(builder);
        List<CaseFollowupRecord> caseFollowupRecords = IterableUtils.toList(recordIterable);
        int codeNumber = caseFollowupRecords.size();
        process.setCodeNumber(codeNumber); //行动代码量

        if (codeNumber > 0) {
            Map<String, List<CaseFollowupRecord>> map = caseFollowupRecords.stream().collect(Collectors.groupingBy(CaseFollowupRecord::getCaseId));
            int touchNumber = map.size();
            process.setTouchNumber(touchNumber); //案件触碰量
            if (touchNumber == 0) {
                process.setPenetrationRate(0f); //渗透率
            } else {
                process.setPenetrationRate(new BigDecimal((double) codeNumber / touchNumber).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue()); //渗透率
            }
            if ((currentCollecting + outCaseNum) == 0) {
                process.setTouchRate(0f); //触碰率
            } else {
                process.setTouchRate(new BigDecimal((double) touchNumber / (currentCollecting + outCaseNum)).setScale(4, BigDecimal.ROUND_HALF_UP).floatValue()); //触碰率
            }
        } else {
            process.setTouchNumber(0); //案件触碰量
            process.setPenetrationRate(0f); //渗透率
            process.setTouchRate(0f); //案件触碰率
        }
        return CompletableFuture.completedFuture(process);
    }
}
